/** 
    @file pixelnode.hpp
    @brief Game room node
*/

#ifndef PM3_PIXELNODE_HPP
#define PM3_PIXELNODE_HPP

#include "dot_scene_loader.hpp"
#include "interface.hpp"
#include "util.hpp"
#include "logger.hpp"
#include "physics.hpp"

#include <OgreSceneNode.h>
#include <OgreEntity.h>

namespace pm3 {
    /**
        @class PIXELNODE
        @brief Game room node
    */
    class PIXELNODE {
    friend class PIXELROOM;
    friend class PIXELOBJ;
    friend class PIXELMAP;
    public:
            /**
                @brief Constructor
            */
            PIXELNODE();
            /**
                @brief Destructor
            */
            virtual ~PIXELNODE();

            //! Ogre scene
            Ogre::DotSceneLoader m_scene;

            /**
                @brief Loads a .scene
                @param[in] r_path Reference to the scene path
                @param[in] r_group Reference to resource group
                @return Entity number on success, -1 on failure
            */
            int load_scene( const std::string &r_path, const std::string &r_group );

            /**
                @brief Loads a entity model
                @param[in] r_path Reference to the model path
                @return Entity number on success, -1 on failure
            */
            int add_model( const std::string &r_path );

            /**
                @brief Adds a node
                @param[in] i_parent Parent node index, which would be -1 for the room node
                @return Node number on success, -1 on failure
            */
            int add_node( int i_parent );
            
            /**
                @brief Attaches a model to a node
                @param[in] i_model Model number
                @param[in] i_node Number of the node to which the model should be attached
                @return 0 on success, -1 on failure
            */
            int attach_model( int i_model, int i_node );

            /**
                @brief Scales a node
                @param[in] i_node Node number
                @param[in] v_scale Scaling vector
                @return 0 on success, -1 on failure
            */
            int scale_node( int i_node, Ogre::Vector3 v_scale );
            /**
                @brief Translates a node
                @param[in] i_node Node number
                @param[in] v_offset Translation offset
                @return 0 on success, -1 on failure
            */
            int translate_node( int i_node, Ogre::Vector3 v_offset );
            /**
                @brief Rotates a node
                @param[in] i_node Node number
                @param[in] v_angles Rotation angles
                @return 0 on success, -1 on failure
            */
            int rotate_node( int i_node, Ogre::Vector3 v_angles );

            /**
                @brief Gets room object pointer
                @return Object pointer or NULL, if this room is still to be set up
            */
            inline class PIXELOBJ* get_obj() const {
                return m_object;
            }

            /**
                @brief Gets room node pointer
                @return Pointer to room node
            */
            inline Ogre::PCZSceneNode* get_node() const {
                return m_node;
            }

            /**
                @brief Checks if the room has been initialized
                @return True if it has, false otherwise
            */
            bool is_initialized() const;

    protected:

            /**
                @brief Initializes the node
                @param[in] p_obj Pointer to the object that corresponds to the node
                @param[in] v_pos 
            */
            void init( class PIXELOBJ *p_obj, Ogre::Vector3 v_pos );

            /**
                @brief Post-sets-up the node (physics mainly)
            */
            void post_setup();

    protected:
            //! Pointer to room object
            class PIXELOBJ *m_object;

            //! Room node
            Ogre::PCZSceneNode *m_node;

            //! Object nodes
            std::vector<Ogre::SceneNode *> m_nodes;
    private:
            //! Entities
            std::vector<Ogre::Entity *> m_entities;

            //! Pointer to bullet rigid body
            std::vector<btRigidBody *> m_rigid_bodies;
            //! Pointer to bullet collision shape
            std::vector<btCollisionShape *> m_collision_shapes;

            /**
                @brief Adds a rigid body based on an entity
                @param[in] p_entity Pointer to the entity
                @param[in] b_dynamic Is the entity static or dynamic?
            */
            void add_body( Ogre::Entity *p_entity, bool b_dynamic = false );

            /**
                @brief Unloads all nodes and entities
            */
            void unload();

            //! Total entity counter
            static int m_num_entities;
            //! Total number of nodes
            static int m_num_nodes;
    };

    namespace lua {
        //! Pointer to the active node to which all called lua functions apply
        extern PIXELNODE *g_active_node;
    }
}

#endif

